package com.pureut.scheduling.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ibm.icu.text.SimpleDateFormat;
import com.pureut.common.core.exception.GlobalException;
import com.pureut.common.core.utils.StringUtils;
import com.pureut.common.core.utils.bean.BeanUtils;
import com.pureut.common.core.web.domain.AjaxResult;
import com.pureut.common.datascope.annotation.DataScope;
import com.pureut.common.security.utils.DictUtils;
import com.pureut.common.security.utils.SecurityUtils;
import com.pureut.scheduling.domain.CalendarLine;
import com.pureut.scheduling.domain.CalendarRest;
import com.pureut.scheduling.domain.CalendarTeam;
import com.pureut.scheduling.domain.SchedulingCalendar;
import com.pureut.scheduling.domain.dto.*;
import com.pureut.scheduling.domain.dto.SysLineDto;
import com.pureut.scheduling.mapper.SchedulingCalendarMapper;
import com.pureut.scheduling.domain.vo.CalendarSpecialVo;
import com.pureut.scheduling.domain.vo.HolidayVo;
import com.pureut.scheduling.domain.vo.SchedulingCalendarVo;
import com.pureut.scheduling.service.ISchedulingCalendarService;
import com.pureut.scheduling.util.HolidayUtil;
import com.pureut.scheduling.util.SchedulingMqUtil;
import com.pureut.scheduling.util.WeekendUtils;
import com.pureut.system.api.FeignService;
import com.pureut.system.api.domain.SysDictData;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.sql.SQLException;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 工厂日历实现类
 * @Date 22-12-29
 * @Author hl
 **/
@Service
public class SchedulingCalendarServiceImpl implements ISchedulingCalendarService {

    @Resource
    private SchedulingCalendarMapper schedulingCalendarMapper;


    @Resource
    private FeignService feignService;

    /**
     * 查询工厂日历
     *
     * @param schedulingCalendarVo 工厂日历接受类
     * @return list schedulingCalendarVo
     */
    @Override
    @DataScope(deptAlias = "scheduling_calendar")
    public List<SchedulingCalendarDto> selectCalendarList(SchedulingCalendarVo schedulingCalendarVo) {
        return schedulingCalendarMapper.selectCalendarList(schedulingCalendarVo);
    }

    /**
     * 新增工厂日历
     *
     * @param schedulingCalendar 工厂日历接受类
     * @return 1 成功 0 失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertSchedulingCalendar(SchedulingCalendar schedulingCalendar) throws Exception {
        schedulingCalendar.setCalendarType(1);
        schedulingCalendar.setDeptId(SecurityUtils.getDeptId());

        int is = schedulingCalendarMapper.countSchedulingCalendar(schedulingCalendar.getCalendarCode());
        if (is > 0) {
            throw new SQLException("编码不允许重复,请重新输入!");
        }
        int ins = schedulingCalendarMapper.insertSchedulingCalendar(schedulingCalendar);
        if (ins > 0) {
            long caId = schedulingCalendar.getCalendarId();
            String str = schedulingCalendar.getCalendarJson();
            JSONObject json = JSONObject.parseObject(str);
              addSchedulingCalendar(json, caId);

            //根据caId获取班组信息
            List<CalendarTeam> calendarTeams = schedulingCalendarMapper.selectCalendarTeamList(caId);
            //mq发送消息
            SchedulingCalendarMqDto schedulingCalendarMqDto = new SchedulingCalendarMqDto();
            BeanUtils.copyProperties(schedulingCalendar, schedulingCalendarMqDto);
            schedulingCalendarMqDto.setCalendarList(calendarTeams);
            SchedulingMqUtil.schedulingCalendarMqSend(schedulingCalendarMqDto);
        } else {
            throw new SQLException("新增失败");
        }
        return ins;
    }

    /**
     * 删除工厂日历
     *
     * @param calendarId 工厂日历ID
     * @return 1 成功 0 失败
     */
    @Override
    public int deleteCalendarById(String calendarId) {
        String[] calendarIdS = calendarId.split(",");
        return schedulingCalendarMapper.deleteCalendarById(calendarIdS);
    }

    /**
     * 修改工厂日历
     *
     * @param schedulingCalendar 接受类
     * @return 1 成功 0 失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateCalendarEdit(SchedulingCalendar schedulingCalendar) throws Exception {
        long caId = schedulingCalendar.getCalendarId();
        int i1 = schedulingCalendarMapper.updateCalendarEdit(schedulingCalendar);
        schedulingCalendarMapper.deleteCalendarTeamById(caId);
        schedulingCalendarMapper.deleteCalendarRestById(caId);
        schedulingCalendarMapper.deleteCalendarLineById(caId);
//        if (op == 0) {
//            throw new SQLException("抛出异常");
//        }
        JSONObject json = JSONObject.parseObject(schedulingCalendar.getCalendarJson());
        int i = addSchedulingCalendar(json, caId);
        if (i > 0) {
            //mq发送消息
            //根据caId获取班组信息
            List<CalendarTeam> calendarTeams = schedulingCalendarMapper.selectCalendarTeamList(caId);
            //mq发送消息
            SchedulingCalendarMqDto schedulingCalendarMqDto = new SchedulingCalendarMqDto();
            BeanUtils.copyProperties(schedulingCalendar, schedulingCalendarMqDto);
            schedulingCalendarMqDto.setCalendarList(calendarTeams);
            SchedulingMqUtil.schedulingCalendarMqSend(schedulingCalendarMqDto);
        }
        return i1;
    }

    /**
     * 查询单个工厂日历
     *
     * @param calendarId Id
     * @return SchedulingCalendarDto 返回工厂日历
     */
    @Override
    public SchedulingCalendarDto selectCalendarById(long calendarId) {
        SchedulingCalendarVo schedulingCalendarVo = new SchedulingCalendarVo();
        schedulingCalendarVo.setCalendarId(calendarId);
        List<SchedulingCalendarDto> list = schedulingCalendarMapper.selectCalendarList(schedulingCalendarVo);
        SchedulingCalendarDto schedulingCalendarDto = new SchedulingCalendarDto();
        schedulingCalendarDto = list.get(0);
        List<CalendarTeam> teamList = schedulingCalendarMapper.selectCalendarTeamList(calendarId);
        CalendarUniformDto dto = new CalendarUniformDto();
        dto.setTeamCode(teamList);
        List<CalendarRest> restList = schedulingCalendarMapper.selectCalendarRestList(calendarId);
        if (restList.size() > 0) {
            for (CalendarRest rest :
                    restList) {
                CalendarTeam calendarTeam = schedulingCalendarMapper.selectCalendarBan(rest.getTeamId(), calendarId);
                if (calendarTeam != null) {
                    rest.setStartTime(calendarTeam.getTeamStartTime());
                    rest.setEndTime(calendarTeam.getTeamEndTime());
                    rest.setTeamInfo(calendarTeam.getTeamInfo());
                }
            }
            dto.setRestCode(restList);
        }
        List<CalendarLine> lineList = schedulingCalendarMapper.selectCalendarLineList(calendarId);
        List<CalendarLineDto> xvList = new ArrayList<CalendarLineDto>();
        for (CalendarLine line :
                lineList) {
            CalendarLineDto cal = new CalendarLineDto();
            cal.setLineCode(line.getLineCode());
            String echoId = line.getEchoId();
            List<Long> ko = new ArrayList<Long>();
            String[] hoIdS = echoId.split(",");
            for (String ho :
                    hoIdS) {
                ko.add(Long.parseLong(ho));
            }
            cal.setShopId(ko);
            xvList.add(cal);
        }
        dto.setLineCodeDto(xvList);
        schedulingCalendarDto.setCalendarJson(dto);
        return schedulingCalendarDto;
    }

    /**
     * 新增特殊日历
     *
     * @param calendarSpecialVo 特殊日历接受类
     * @return 1 成功 0 失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertCalendarSpecia(CalendarSpecialVo calendarSpecialVo) throws Exception {
        calendarSpecialVo.setCalendarType(2);
        int is = schedulingCalendarMapper.countSchedulingCalendar(calendarSpecialVo.getCalendarCode());
        if (is > 0) {
            throw new SQLException("编码不允许重复,请重新输入!");
        }
        int ins = schedulingCalendarMapper.insertCalendarSpecia(calendarSpecialVo);
        if (ins == 0) {
            throw new SQLException("抛出异常");
        }
        JSONArray arr = calendarSpecialVo.getCalendarJson().getJSONArray("lineCode");
        List<CalendarLine> list = JSONArray.parseArray(arr.toJSONString(), CalendarLine.class);
        for (CalendarLine calendarLine :
                list) {
            calendarLine.setCalendarId(calendarSpecialVo.getCalendarId());
            String shopId = calendarLine.getShopId();
            String[] shopIdS = shopId.split(",");
            int len = shopIdS.length;
            calendarLine.setShopId(shopIdS[len - 1]);
            calendarLine.setEchoId(shopId);
        }
        int jk = schedulingCalendarMapper.insertCalendarLine(list);
        if (jk == 0) {
            throw new SQLException("抛出异常");
        }
        return jk;
    }

    /**
     * 查询特殊日历
     *
     * @param calendarSpecialVo 特殊日历接受类
     * @return List<CalendarSpecialDto> 特殊日历返回类
     */
    @Override
    public List<CalendarSpecialDto> selectCalendarSpecialList(CalendarSpecialVo calendarSpecialVo) {
        return schedulingCalendarMapper.selectCalendarSpecialList(calendarSpecialVo);
    }

    /**
     * 批量删除特殊日历
     *
     * @param calendarId 特殊日历Id
     * @return AjaxResult
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteCalendarSpecialById(String calendarId) throws Exception {
        String[] calendarIdS = calendarId.split(",");
        int ins = schedulingCalendarMapper.deleteCalendarSpecialById(calendarIdS);
        if (ins == 0) {
            throw new SQLException("抛出异常");
        }
        int kl = 0;
        for (String lp :
                calendarIdS) {
            kl = schedulingCalendarMapper.deleteCalendarLineById(Long.parseLong(lp));
            if (kl == 0) {
                throw new SQLException("抛出异常");
            }
        }
        return kl;
    }

    /**
     * 修改特殊日历
     *
     * @param calendarSpecialVo 特殊日历接受
     * @return 1 成功 0 失败
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateCalendarSpecialEdit(CalendarSpecialVo calendarSpecialVo) throws Exception {
        int ins = schedulingCalendarMapper.updateCalendarSpecialEdit(calendarSpecialVo);
        int jk = 0;
        if (ins > 0) {
            ins = schedulingCalendarMapper.deleteCalendarLineById(calendarSpecialVo.getCalendarId());
            if (ins == 0) {
                throw new SQLException("抛出异常");
            } else {
                JSONObject json = calendarSpecialVo.getCalendarJson();
                JSONArray arr = json.getJSONArray("lineCode");
                List<CalendarLine> list = JSONArray.parseArray(arr.toJSONString(), CalendarLine.class);
                for (CalendarLine calendarLine :
                        list) {
                    calendarLine.setCalendarId(calendarSpecialVo.getCalendarId());
                    String shopId = calendarLine.getShopId();
                    String[] shopIdS = shopId.split(",");
                    int len = shopIdS.length;
                    calendarLine.setShopId(shopIdS[len - 1]);
                    calendarLine.setEchoId(shopId);
                }
                jk = schedulingCalendarMapper.insertCalendarLine(list);
                if (jk == 0) {
                    throw new SQLException("抛出异常");
                }
            }
        } else {
            throw new SQLException("抛出异常");
        }
        return jk;
    }


    /**
     * 查询单个特殊日历
     *
     * @param calendarId 特殊日历id
     * @return CalendarSpecialDto 特殊工厂日历返回类
     */
    @Override
    public CalendarSpecialDto selectCalendarSpecialById(long calendarId) {
        CalendarSpecialVo calendarSpecialVo = new CalendarSpecialVo();
        calendarSpecialVo.setCalendarId(calendarId);
        List<CalendarSpecialDto> list = schedulingCalendarMapper.selectCalendarSpecialList(calendarSpecialVo);
        CalendarSpecialDto calendarSpecialDto = new CalendarSpecialDto();
        calendarSpecialDto = list.get(0);
        List<CalendarLine> lineList = schedulingCalendarMapper.selectCalendarLineList(calendarId);
        CalendarUniformLineDto dto = new CalendarUniformLineDto();
        List<CalendarLineDto> xvList = new ArrayList<CalendarLineDto>();
        for (CalendarLine line :
                lineList) {
            CalendarLineDto cal = new CalendarLineDto();
            cal.setLineCode(line.getLineCode());
            String echoId = line.getEchoId();
            List<Long> ko = new ArrayList<Long>();
            String[] hoIdS = echoId.split(",");
            for (String ho :
                    hoIdS) {
                ko.add(Long.parseLong(ho));
            }
            cal.setShopId(ko);
            xvList.add(cal);
        }
        dto.setLineDto(xvList);
        calendarSpecialDto.setCalendarJson(dto);
        return calendarSpecialDto;
    }

    /**
     * 日历查看
     *
     * @param year 年,month 月
     * @return List<HolidayVo> 日历查看返回类
     */
    public List<HolidayVo> selectCalendarViewing(int year, int month, long lineId) throws IOException {
        int count = schedulingCalendarMapper.countCalendarLineOnById(lineId);
        if (count == 0) {
            throw new GlobalException("该线别不存在日历!");
        } else if (count > 1) {
            throw new GlobalException("该线别存在多个日历!");
        }
        long calId = schedulingCalendarMapper.selectCalendarLineOnById(lineId);
        List<HolidayVo> holidayVoList = new ArrayList<>();
        SchedulingCalendarVo caVo = new SchedulingCalendarVo();
        caVo.setCalendarId(calId);
        List<SchedulingCalendarDto> listDto = schedulingCalendarMapper.selectCalendarList(caVo);
        SchedulingCalendarDto dto = listDto.get(0);
        int holiday = dto.getCalendarHolidayWork(); //节假日上班
        int saturday = dto.getCalendarSaturdayWork();//周六上班
        int weekend = dto.getCalendarWeekendWork();//周日上班
        List<HolidayVo> weekList = new ArrayList<>();
        if (holiday == 2) {
            //上班
            String rqi = year + "-" + month;
            holidayVoList = HolidayUtil.getAllHolidayByYear(rqi);
        }
        if (saturday == 2) {
            weekList = WeekendUtils.getWeekendInMonthSaturday(year, month);
            holidayVoList.addAll(weekList);
        }
        if (weekend == 2) {
            weekList = WeekendUtils.getWeekendInMonthSunday(year, month);
            holidayVoList.addAll(weekList);
        }
        holidayVoList = new ArrayList<>(new HashSet<>(holidayVoList)); //去重
        holidayVoList.sort(Comparator.comparing(HolidayVo::getData)); //排序
        return holidayVoList;
    }


    /**
     * 日历查看
     *
     * @param year 年,month 月
     * @return List<HolidayVo> 日历查看返回类
     */
 /*   @Override
    public List<HolidayVo> selectCalendarViewing(int year, int month, long lineId) throws IOException {
        long calId = schedulingCalendarMapper.selectCalendarLineOnById(lineId);
        List<HolidayVo> HolidayVoList = new ArrayList<HolidayVo>();
        SchedulingCalendarVo caVo = new SchedulingCalendarVo();
        caVo.setCalendarId(calId);
        List<SchedulingCalendarDto> ListDto = schedulingCalendarMapper.selectCalendarList(caVo);
        SchedulingCalendarDto dto = ListDto.get(0);
        int Holiday = dto.getCalendarHolidayWork(); //节假日上班
        int saturday = dto.getCalendarSaturdayWork();//周六上班
        int weekend = dto.getCalendarWeekendWork();//周日上班
        List<HolidayVo> weekList = new ArrayList<HolidayVo>();
        if(Holiday==1){
            //上班
            String rqi = String.valueOf(year)+"-"+String.valueOf(month);
            HolidayVoList = HolidayUtil.getAllHolidayByYear(rqi);
        }
        if(saturday ==1 && weekend==1){
            weekList = WeekendUtils.getWeekendInMonth(year,month);
            HolidayVoList.addAll(weekList);
        }else if(saturday ==1 && weekend!=1){
            weekList = WeekendUtils.getWeekendInMonthSaturday(year,month);
            HolidayVoList.addAll(weekList);
        }else if(saturday !=1 && weekend==1){
            weekList = WeekendUtils.getWeekendInMonthSunday(year,month);
            HolidayVoList.addAll(weekList);
        }
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd");
        HolidayVoList.sort((a,b)->{//排序
            try {
                return sf.parse(a.getData()).compareTo(sf.parse(b.getData()));
            } catch (ParseException e) {
                e.printStackTrace();
            }
            return 1;
        });
        //去除重复数据
        for (int i =0;i<HolidayVoList.size();i++){
            if(i+1<HolidayVoList.size()){
                HolidayVo vo  = HolidayVoList.get(i);
                HolidayVo vo2  = HolidayVoList.get(i+1);
                if(vo.getData().equals(vo2.getData())){
                    HolidayVoList.remove(i+1);
                }
            }
        }
        return HolidayVoList;
    }*/

    /**
     * 工厂日历提取json并保存
     */
    @Transactional(rollbackFor = Exception.class)
    public int addSchedulingCalendar(JSONObject json, long caId) throws Exception {
        JSONArray arr = json.getJSONArray("teamCode");
        JSONArray arr2 = json.getJSONArray("restCode");
        JSONArray arr3 = json.getJSONArray("lineCodeDto");
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
        List<CalendarTeam> list = JSONArray.parseArray(arr.toJSONString(), CalendarTeam.class);
        int ins = 0;
        if (list.size() > 0) {
            for (CalendarTeam team :
                    list) {
                team.setCalendarId(caId);
                long diff = 0;
                String teamEnd = team.getTeamEndTime();
                long startTime = sdf.parse(team.getTeamStartTime()).getTime();
                if (team.getTeamTranssky() == 1) {
                    //代表跨天
                    String[] teamPoints = teamEnd.split(":");
                    int points = 24 + Integer.parseInt(teamPoints[0]);
                    teamEnd = points + teamPoints[1];
                }
                long endTime = sdf.parse(teamEnd).getTime();
                diff = (endTime - startTime) / 1000 / 60;
                team.setTeamMinute((int) diff);
            }
            ins = schedulingCalendarMapper.insertCalendarTeam(list);
            if (ins == 0) {
                throw new SQLException("抛出异常");
            }
        }
        List<CalendarRest> list2 = JSONArray.parseArray(arr2.toJSONString(), CalendarRest.class);
        if (list2.size() > 0) {
            if (!StringUtils.isEmpty(list2.get(0).getTeamId())) {
                for (CalendarRest rest :
                        list2) {
                    rest.setCalendarId(caId);
                    String restEnd = rest.getRestEndTime();
                    if (rest.getRestTranssky() == 1) {
                        //代表跨天
                        String[] reamPoints = restEnd.split(":");
                        int points1 = 24 + Integer.parseInt(reamPoints[0]);
                        restEnd = points1 + reamPoints[1];
                    }
                    long restStartTime = sdf.parse(rest.getRestStartTime()).getTime();
                    long restEndTime = sdf.parse(restEnd).getTime();
                    long restDiff = (restEndTime - restStartTime) / 1000 / 60;
                    rest.setRestMinute((int) restDiff);
                }
                ins = schedulingCalendarMapper.insertCalendarRest(list2);
                if (ins == 0) {
                    throw new SQLException("抛出异常");
                }
            }
        }
        List<CalendarLine> list3 = JSONArray.parseArray(arr3.toJSONString(), CalendarLine.class);
        if (list3.size() > 0) {
            for (CalendarLine line :
                    list3) {
                line.setLineId(0);
                String shopId = line.getShopId();
                String[] shopIdS = shopId.split(",");
                int len = shopIdS.length;
                line.setShopId(shopIdS[len - 1]);
                line.setEchoId(shopId);
                line.setCalendarId(caId);
                int kl = schedulingCalendarMapper.countCheckCalendarLine(line.getShopId());
                if (kl > 0) {
                    throw new SQLException("已存在该线别的工厂日历,请重新选择线别!");
                }
            }
            ins = schedulingCalendarMapper.insertCalendarLine(list3);
            if (ins == 0) {
                throw new SQLException("抛出异常");
            }
        }
        return ins;
    }

    /**
     * 工厂日历下拉菜单
     *
     * @param calendarSpecialVo
     * @return
     */
    @Override
    public List<ShopCalendarDto> selectShopCalendarList(CalendarSpecialVo calendarSpecialVo) {
        return schedulingCalendarMapper.selectShopCalendarList(calendarSpecialVo);
    }

    /**
     * 根据工厂id查询班次
     *
     * @param calendarId
     * @return 下拉菜单
     */
    @Override
    public List<ShiftCalendarDto> selectShiftCalendarList(Long calendarId) {

        //根据字典查询班组
        List<SysDictData> statusArray = DictUtils.getDictCache("scheduling_class_info");
        Map<String, String> statusMap = statusArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        List<ShiftCalendarDto> shiftCalendarDtoList = schedulingCalendarMapper.selectShiftCalendarDto(calendarId);
        if (shiftCalendarDtoList == null) {
            throw new GlobalException("该班次不存在");
        }
        for (ShiftCalendarDto shiftCalendarDto : shiftCalendarDtoList) {
            // 班组
            shiftCalendarDto.setTeamInfoDict(statusMap.get(String.valueOf(shiftCalendarDto.getTeamInfo())));
        }

        return shiftCalendarDtoList;
    }

    /**
     * 根据工厂日历查询线别
     *
     * @param calendarId
     * @return
     */
    @Override
    public List<LineTypeCalendarDto> selectLineTypeCalendarList(Long calendarId) {
        List<LineTypeCalendarDto> lineTypeCalendarDtos = schedulingCalendarMapper.selectLineTypeCalendarList(calendarId);

        if (lineTypeCalendarDtos == null) {
            throw new GlobalException("该线别不存在");
        }
        for (LineTypeCalendarDto lineTypeCalendarDto : lineTypeCalendarDtos) {
            Long lineId = lineTypeCalendarDto.getLineId();
            AjaxResult modelingLine = feignService.getModelingLineInfo(lineTypeCalendarDto.getLineCode());
            SysLineDto sysLineDto = JSON.parseObject(JSON.toJSONString(modelingLine.get("data")), SysLineDto.class);
            lineTypeCalendarDto.setLineName(sysLineDto.getLineName());
        }

        return lineTypeCalendarDtos;
    }

    /**
     * 根据工厂日历id查询班别设置信息
     *
     * @param calendarId
     * @return feign远程调用
     */
    @Override
    public List<ShiftSettingDto> selectShiftSettingList(Long calendarId) {

        //根据字典查询班组
        List<SysDictData> statusArray = DictUtils.getDictCache("scheduling_class_info");
        Map<String, String> statusMap = statusArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));

        List<ShiftSettingDto> shiftSettingDtos = schedulingCalendarMapper.selectShiftSettingList(calendarId);
        if (shiftSettingDtos == null) {
            throw new GlobalException("该班别信息不存在");
        }
        for (ShiftSettingDto shiftSettingDto : shiftSettingDtos) {
            // 班组
            shiftSettingDto.setTeamInfoDict(statusMap.get(String.valueOf(shiftSettingDto.getTeamInfo())));
        }

        return shiftSettingDtos;
    }

    /**
     * 根据线别编码查询班次信息
     *
     * @param lineCode
     * @return feign远程调用
     */
    @Override
    public List<ShiftSettingDto> selectShiftLine(String lineCode) {
        return schedulingCalendarMapper.selectShiftLine(lineCode);
    }


}
